Skip to content

Rework ArrayReplaceFunctionReturnTypeExtension #3958

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: 1.12.x
Choose a base branch
from

Conversation

VincentLanglet
Copy link
Contributor

@VincentLanglet VincentLanglet commented Apr 21, 2025

Close phpstan/phpstan#12828

I basically copy the ArrayMergeFunctionReturnTypeExtension with the following change

$keyType instanceof ConstantIntegerType ? null : $keyType,

$keyType instanceof ConstantIntegerType ? null : $keyType, is replaced by $keyType because

  • array_merge reindex numeric keys
  • array_replace keep all the existing keys

if (!(new IntegerType())->isSuperTypeOf($keyType)->yes()) {

if (!(new IntegerType())->isSuperTypeOf($keyType)->yes()) { is replaced by if (!$argType->isList()->yes()) { because of the same reason.

@VincentLanglet VincentLanglet marked this pull request as ready for review April 22, 2025 08:44
@phpstan-bot
Copy link
Collaborator

This pull request has been marked as ready for review.

@herndlm
Copy link
Contributor

herndlm commented Apr 22, 2025

I know I'm maybe a bit fast suggesting this, but we could create a Type::mergeArray() or Type::replaceArray() with a proper $preserveKeys or $reindex arg or whatever and then us it in both return type extensions. And maybe I should have done this already the last time I touched the merge one. Anyway, can be done in a follow-up too IMO, so this comment should not be considered a blocker IMO 😊 and I can volunteer to do this.

assertType("non-empty-array<'bar'|'foo', '1'|'2'|'4'>", array_replace($array1, $array2));
assertType("array{foo: '1', bar: '2'}", array_replace($array1));
assertType("array{foo: '1', bar: '2'}", array_replace([], $array1));
assertType("array{foo: '1', bar: '4'}", array_replace($array1, $array2));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add another test cases where $array2 is a general array, please? And maybe in the other section somewhere also one where $array1 is a general array but $array2 is a constant array.

a bit more mixed keys (strings or ints) would be interesting too 😊 that would also help massively with potential future refactoring

@VincentLanglet
Copy link
Contributor Author

Anyway, can be done in a follow-up too IMO, so this comment should not be considered a blocker IMO 😊 and I can volunteer to do this.

Yeah, I would prefer this to be done in a follow up PR to separate (and validate separately by ondrej)

  • The new implementation
  • The refactoring

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants